package cn.yh.nft.turbo.limiter;

import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;

/**
 * @ClassName: SlidingWindowRateLimiter
 * @Author: 草莓爱上啵啵
 *
 *  滑动窗口限流服务
 */
public class SlidingWindowRateLimiter implements RateLimiter{

    /**
     * 声明一个RedissonClient实例变量，用于与Redis交互
     */
    private RedissonClient redissonClient;

    /**
     * 定义限流键的前缀常量，用于Redis中存储限流数据
     */
    private static final String LIMIT_KEY_PREFIX = "nft:turbo:limit:";

    /**
     * 构造函数，接收RedissonClient实例并赋值给成员变量
     * @param redissonClient RedissonClient实例
     */
    public SlidingWindowRateLimiter(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    /**
     *  实现RateLimiter接口的tryAcquire方法
     * @param key 限流的key
     * @param limit 限流的数量
     * @param windowSize 窗口大小，单位为秒
     * @return
     */
    @Override
    public Boolean tryAcquire(String key, int limit, int windowSize) {
        //获取或创建基于Redis的RateLimiter实例
        //使用LIMIT_KEY_PREFIX和传入的key组合作为Redis中的键名
        RRateLimiter rRateLimiter = redissonClient.getRateLimiter(LIMIT_KEY_PREFIX + key);

        //检查该RateLimiter是否已存在(即是否已初始化)
        if (!rRateLimiter.isExists()) {
            //如果不存在，则初始化RateLimiter
            //RateType.OVERALL: 表示总体限制
            //limit: 限制数量
            //windowSize: 时间窗口大小
            //RateIntervalUnit.SECONDS: 时间单位是秒
            rRateLimiter.trySetRate(RateType.OVERALL, limit, windowSize, RateIntervalUnit.SECONDS);
        }

        //尝试获取许可(即检查是否在限制范围内)
        //返回true表示获取成功(未超过限制)，false表示超过限制
        return rRateLimiter.tryAcquire();
    }
}
